package com.think.oauth.user.controller;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.web.bind.annotation.*;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.think.common.controller.BaseController;
import com.think.common.model.CustomUser;
import com.think.common.utils.Common;
import com.think.oauth.user.constant.EmailType;
import com.think.oauth.user.constant.ResultCode;
import com.think.oauth.user.model.Result;
import com.think.oauth.user.model.User;
import com.think.oauth.user.model.UserOauth;
import com.think.oauth.user.service.PermissionService;
import com.think.oauth.user.service.SendMailService;
import com.think.oauth.user.service.UserOauthService;
import com.think.oauth.user.service.UserService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

@Api(description = "用户操作接口")
@RestController
@RequestMapping("/v1/user")
public class UserController extends BaseController {

	@Autowired
	private UserService userService;
	
	@Autowired
	private UserOauthService oauthService;
	
	@Value("${custom.useEmail}")
	private Boolean useEmail;
	
	@Autowired
	private SendMailService sendMailService;
	
	@Autowired
	private PermissionService permissionService;
	@Autowired
    PasswordEncoder passwordEncoder;
	
	@ApiOperation(value = "获取用户信息", notes = "通过前端调用令牌获取用户详细信息")
	@RequestMapping(value = "/info", method = RequestMethod.GET)
	public void getUserInfo(HttpServletRequest request, HttpServletResponse response) {
		CustomUser user = Common.GetCurrentAuthor();
		User res = userService.getById(user.getUserId());
		
		if (res == null) {
			outputJson(Result.failure(ResultCode.USER_NOT_EXIST), request, response);
			return;
		}
		res.setLoginType(user.getLoginType());
		res.setPermissions(permissionService.getBaseMapper().selectPermissionByUserId(user.getUserId(),Common.GetClient()));
		outputJson(Result.success(res), request, response);
	}
	
	
	@ApiOperation(value = "用户注册", notes = "通过前端调用令牌获取用户详细信息")
	@ApiImplicitParams(value = {
			@ApiImplicitParam(name="username",value="用户名",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="password",value="密码",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="emailCode",value="邮箱验证码",required=false,paramType="form",dataType="Integer"),
		    @ApiImplicitParam(name="email",value="邮箱",required=false,paramType="form",dataType="Integer")

	})
	@RequestMapping(value = "/register", method = RequestMethod.POST)
	public Result userRegister(@RequestParam("username")String username
			,@RequestParam("password")String password
			,@RequestParam(value =  "emailCode",required = false,defaultValue = "") String emailCode
			,@RequestParam(value =  "email",required = false,defaultValue = "") String email
			, HttpServletRequest request, HttpServletResponse response) {
	
		if (oauthService.checkUserExits(username, Common.USER_USERNAME_LOGIN)) {
			return Result.failure(ResultCode.USER_HAS_EXISTED);
		}
		else if (!sendMailService.verification(email, emailCode) && useEmail) {
			return Result.failure(ResultCode.PARM_EMAIL_CODE_INVALID);
		}
		else {
			User user = new User();
			user.setName(username);
			user.setNickname(username);
			user.setEmail(email);
			ArrayList<UserOauth> oauths = new ArrayList<UserOauth>();
			UserOauth oauth = new UserOauth();
			oauth.setLoginType(Common.USER_USERNAME_LOGIN);
			oauth.setIdentifier(username);
			oauth.setCredential(passwordEncoder.encode(password));
			oauths.add(oauth);
			if (useEmail) {
				UserOauth emailOauth = new UserOauth();
				emailOauth.setLoginType(Common.USER_EMAIL_LOGIN);
				emailOauth.setIdentifier(email);
				emailOauth.setCredential(passwordEncoder.encode(password));
				oauths.add(emailOauth);
			}
			try {
				
				userService.insertUser(user, oauths);
			} catch (Exception e) {
				// TODO: handle exception
				return Result.failure(ResultCode.USER_DATA_DUPLICICATE);
			}
			
			return Result.success(user);
		}
		
	}
	
	@ApiOperation(value = "用户注册", notes = "通过前端调用令牌获取用户详细信息")
	 @ApiImplicitParam(name="email",value="邮箱地址省份",required=true,paramType="form",dataType="String")
	@RequestMapping(value = "/emailCode", method = RequestMethod.POST)
	public Result userRegisterEmail(String email, HttpServletRequest request, HttpServletResponse response) {

		System.out.println("用户注册发送的邮箱地址===-------"+email);
		if (true) {
			sendMailService.sendMail(email,EmailType.REGISTER_ACCOUNT);
		}
		return Result.success();
	}
	
	@ApiOperation(value = "用户找回密码", notes = "")
	 @ApiImplicitParam(name="email",value="邮箱地址",required=true,paramType="form",dataType="String")
	@RequestMapping(value = "/retriveCode", method = RequestMethod.POST)
	public Result userRetriveEmail(String email, HttpServletRequest request, HttpServletResponse response) {
	
		if (true) {
			sendMailService.sendRetriveMail(email);
		}
		return Result.success();
	}
	
	
	@ApiOperation(value = "用户修改密码", notes = "通过前端调用令牌获取用户详细信息")
	@ApiImplicitParams(value = {
			@ApiImplicitParam(name="oldPwd",value="原密码",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="newPwd",value="新密码",required=false,paramType="form",dataType="String"),

	})
	@RequestMapping(value = "/password", method = RequestMethod.POST)
	public Result userChangePassword(String oldPwd,String newPwd, HttpServletRequest request, HttpServletResponse response) {
		
		UserOauth oauth = oauthService.getUserOauthInfo(Common.GetCurrentAuthor().getUserId());
		if (oauth != null) {
			if (passwordEncoder.matches(oldPwd, oauth.getCredential())) {
				if(oauthService.updateUserOauth(oauth.getIdentifier(), oauth.getLoginType(), passwordEncoder.encode(newPwd))) {
					return Result.success();
				}
				else {
					return Result.failure(ResultCode.SYSTEM_INNER_ERROR);
				}
			}
			else {
				return Result.failure(ResultCode.USER_PASSWOR_ERROR);
			}
		}
		else {
			return Result.failure(ResultCode.USER_INFO_NOT_FOUND);

		}
	}
	
	@ApiOperation(value = "用户修改密码", notes = "通过前端调用令牌获取用户详细信息")
	@ApiImplicitParams(value = {
			@ApiImplicitParam(name="username",value="用户名",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="password",value="密码",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="emailCode",value="邮箱验证码",required=false,paramType="form",dataType="Integer"),
		    @ApiImplicitParam(name="email",value="邮箱",required=false,paramType="form",dataType="Integer")

	})
	@RequestMapping(value = "/retrive", method = RequestMethod.POST)
	public Result userRetrivePassword(String username,String email,String password,String emailCode, HttpServletRequest request, HttpServletResponse response) {
		
		UserOauth userNameOauth = oauthService.getUserOauth(username, Common.USER_USERNAME_LOGIN);
		UserOauth emailOauth = oauthService.getUserOauth(email, Common.USER_EMAIL_LOGIN);
		
		if (userNameOauth == null) {
			return Result.failure(ResultCode.USER_NAME_NOT_FOUND);
		}
		if (emailOauth == null) {
			return Result.failure(ResultCode.USER_EMAIL_NOT_FOUND);
		}
		if (userNameOauth.getUserId() != emailOauth.getUserId()) {
			return Result.failure(ResultCode.USER_EMAIL_NAME_NOT_PAIR);
		}
		if (!sendMailService.verificationRetrive(email, emailCode)) {
			return Result.failure(ResultCode.PARM_EMAIL_CODE_INVALID);
		}
		if(oauthService.updateUserOauth(username, userNameOauth.getLoginType(), passwordEncoder.encode(password))) {
			return Result.success();
		}
		else {
			return Result.failure(ResultCode.SYSTEM_INNER_ERROR);
		}
	}

	@RequestMapping(value = "test", method = RequestMethod.GET)
	public void teacherList(HttpServletRequest request, HttpServletResponse response) {
		if (isLoggedIn(request)) {
			OAuth2Authentication authentication = (OAuth2Authentication) SecurityContextHolder.getContext()
					.getAuthentication();
			Object user = authentication.getPrincipal();

			outputJson(Result.success(userService.page((IPage<User>) new Page(1, 10))), request, response);
		} else {
			IPage<User> userPage = new Page<>(1, 10);
			QueryWrapper<User> queryWrapper = new QueryWrapper<>();
			queryWrapper.select(User.class, info -> !info.getColumn().equals("created_time")
					&& !info.getColumn().equals("updated_time") && !info.getColumn().equals("del_flag"));
			outputJson(Result.success(userService.page(userPage, queryWrapper)), request, response);
		}

	}

	public static boolean isLoggedIn(HttpServletRequest request) {
		// check the user is not the anonymous one
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		return (authentication != null) && !(authentication instanceof AnonymousAuthenticationToken);
	}

	@ApiOperation(value = "修改用户信息", notes = "通过前端调用令牌获取修改详细信息")
	@ApiImplicitParams(value = {
			@ApiImplicitParam(name="avatarUrl",value="头像",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="city",value="城市",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="country",value="国家",required=false,paramType="form",dataType="Integer"),
		    @ApiImplicitParam(name="gender",value="性别",required=false,paramType="form",dataType="Integer"),
		    @ApiImplicitParam(name="nickname",value="昵称",required=false,paramType="form",dataType="Integer"),
		    @ApiImplicitParam(name="phone",value="手机号",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="province",value="省份",required=false,paramType="form",dataType="String"),
		    @ApiImplicitParam(name="birthday",value="生日",required=false,paramType="form",dataType="String"),


	})
	@RequestMapping(value = "/info", method = RequestMethod.POST)
	public void updateUserInfo(HttpServletRequest request, HttpServletResponse response,
			@RequestParam(value = "avatarUrl", required = false, defaultValue = "") String avatarUrl,
			@RequestParam(value = "city", required = false, defaultValue = "") String city,
			@RequestParam(value = "country", required = false, defaultValue = "") String country,
			@RequestParam(value = "gender", required = false, defaultValue = "-1") Integer gender,
			@RequestParam(value = "nickname", required = false, defaultValue = "") String nickname,
			@RequestParam(value = "phone", required = false, defaultValue = "") String phone,
			@RequestParam(value = "birthday", required = false) Timestamp birthday,
			@RequestParam(value = "province", required = false, defaultValue = "") String province) {
		Result result = null;
		OAuth2Authentication authentication = (OAuth2Authentication) SecurityContextHolder.getContext()
				.getAuthentication();
		CustomUser user = (CustomUser) authentication.getPrincipal();
		User res = userService.selectUserWithOauth(user.getUsername(), user.getLoginType());
		if (res == null) {
			result = Result.failure(ResultCode.USER_NOT_EXIST);
			return;
		} else {

			if (!avatarUrl.isEmpty())
				res.setAvatarUrl(avatarUrl);
			if (!city.isEmpty())
				res.setCity(city);
			if (!country.isEmpty())
				res.setCountry(country);
			if (gender >= 0 && gender <= 2)
				res.setGender(gender);
			if (!nickname.isEmpty())
				res.setNickname(nickname);
			if (!phone.isEmpty())
				res.setPhone(phone);
			if (!province.isEmpty())
				res.setProvince(province);
			if (birthday!=null) {
				res.setBirthday(birthday);
			}
			res.checkObjectIsComplete();
			boolean r = userService.updateById(res);
			if (r) {
				result = Result.failure(ResultCode.SYSTEM_INNER_ERROR);
			} else {
				result = Result.success(res);
			}
		}
		outputJson(result, request, response);
	}

}
